﻿using System.Linq;

namespace BorgExt
{
    internal class ExtensionBuilder
    {
        private int _nextExtensionId = 1;
        private int _nextPlugId = 1;
        private int _nextSlotId = 1;

        internal Extension CreateExtension(ExtensionType extensionType, Qualifier qualifier)
        {
            var extension = new Extension(NextExtensionId(), extensionType);
            var plugs = new MetaElementCollection<Plug>(extensionType.PlugTypes.Count);

            foreach (var plug in extensionType.PlugTypes.
                Select(plugType => CreatePlug(plugType, extension)))
                plugs.Add(plug);

            extension.Plugs = plugs;

            var slots = new MetaElementCollection<Slot>(extensionType.SlotTypes.Count);

            foreach (var slot in extensionType.SlotTypes.
                Select(slotType => CreateSlot(slotType, extension)))
                slots.Add(slot);

            extension.Slots = slots;
            
            return extension;
        }

        internal Plug CreatePlug(PlugType plugType, Extension extension)
        {
            var plug = new Plug(NextPlugId(), plugType, extension);
            var @params = new MetaElementCollection<Param>();
            
            foreach (var element in plugType.Params)
                @params.Add(element);

            var slotDef = plugType.SlotDefinition;

            if (slotDef != null)
                foreach (ParamDefinition paramDef in slotDef.ParamDefinitions.
                    Where(paramDefinition =>
                        paramDefinition.DefaultParam != null &&
                        !@params.Contains(paramDefinition.Name)))
                    @params.Add(paramDef.DefaultParam);

            plug.Params = @params;

            return plug;
        }

        internal Slot CreateSlot(SlotType slotType, Extension extension)
        {
            return new Slot(NextSlotId(), slotType, extension);
        }

        internal int NextExtensionId()
        {
            return _nextExtensionId++;
        }

        internal int NextPlugId()
        {
            return _nextPlugId++;
        }

        internal int NextSlotId()
        {
            return _nextSlotId++;
        }
    }
}

